﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Alma.Models;

namespace Alma.Core
{
    class SearchAnalyzer : ISearchExpressionProcessor
    {
        private enum State
        {
            Undefined,
            InAnd,
            InOr,
            InNot
        }

        private AdvancedSearchModel _model;
        private State _state = State.Undefined;

        public SearchAnalyzer(AdvancedSearchModel target)
        {
            _model = target;
        }

        public void Process(SearchAnd ex)
        {
            ex.Left.Accept(this);
            ex.Right.Accept(this);
        }

        public void Process(SearchOr ex)
        {
            var prevState = _state;
            _state = State.InOr;
            ex.Left.Accept(this);
            ex.Right.Accept(this);
            _state = prevState;
        }

        public void Process(SearchNot ex)
        {
            var prevState = _state;
            _state = State.InNot;
            ex.Inner.Accept(this);
            _state = prevState;
        }

        public void Process(SearchWord ex)
        {
            if (_state == State.InOr)
                _model.SomeWords += " " + ex.Value;
            else if (_state == State.InNot)
                _model.NoneWord += " " + ex.Value;
            else
            {
                var isOnlyAlpha = true;
                foreach (var c in ex.Value)
                    if (!char.IsLetterOrDigit(c))
                    {
                        isOnlyAlpha = false;
                        break;
                    }
                if (isOnlyAlpha)
                    _model.AllWords += " " + ex.Value;
                else
                    _model.Expression += ex.Value;
            }
        }

        public void Process(SearchSelector ex)
        {
            switch (ex.Selector)
            {
                case "cat":
                    var cat = _model.CategoriesItems.SingleOrDefault(x => x.Text == ex.Value);
                    if (cat != null)
                        cat.Selected = true;
                    break;
                case "sec":
                    var sec = _model.SectionItems.SingleOrDefault(x => x.Text == ex.Value);
                    if (sec != null)
                        sec.Selected = true;
                    break;
            }
        }

        public void Process(SearchCriterion ex)
        {
            _model.Criterions.Add(new CriterionComparer()
                                      {
                                          Target = ex.Criterion,
                                          Operator = ex.Operator,
                                          Value = ex.Value
                                      });
        }

        public void Process(SearchRequest ex)
        {
            ex.Expression.Accept(this);
        }

        public AdvancedSearchModel Result { get { return _model;  } }
    }
}